package com.yy.device.boot;

import io.netty.channel.ChannelHandlerContext;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 数据容器
 *
 * @author sunzhiqiang
 * @date 2022/06/16 10:12:36
 */
@Slf4j
@Data
public final class DeviceDataContainer {

    /**
     * 客户端 ctx 存储，用于注册，管理，发送信息等
     * key = 设备点位
     * value = netty ChannelHandlerContext
     */
    public static final Map<Integer, ChannelHandlerContext> CONTEXT_MAP = new ConcurrentHashMap<>();
    /**
     * key=设备code
     * value=netty ChannelHandlerContext
     */
    public static final Map<Integer, List<Short>> DEVICE_DATA_MAP = new ConcurrentHashMap<>();

    private DeviceDataContainer() {
    }

    /**
     * 监控
     */
    public static Map<Integer, ChannelHandlerContext> getOnlineDevices() {
        return CONTEXT_MAP;
    }

    /**
     * 注册:
     * 1-存储点位跟链接的关系映射
     * 2-存储设备跟链接的关系映射-下发任务找链接
     *
     * @param ip  设备点位编号
     * @param ctx ctx
     */
    public static void register(int ip, ChannelHandlerContext ctx) {
        CONTEXT_MAP.put(ip, ctx);
    }

    /**
     * 卸载
     *
     * @param ctx ctx
     */
    public static void unRegister(ChannelHandlerContext ctx) {
        Iterator<Map.Entry<Integer, ChannelHandlerContext>> iterator = CONTEXT_MAP.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Integer, ChannelHandlerContext> next = iterator.next();
            Integer key = next.getKey();
            if (StringUtils.equals(next.getValue().pipeline().channel().id().toString(), ctx.pipeline().channel().id().toString())) {
                log.info("device client lost connect,devicePointCode:{}", key);
                iterator.remove();
                DEVICE_DATA_MAP.remove(key);
            }
        }
    }


    /**
     * 获取 ctx
     *
     * @return short
     */
    public static ChannelHandlerContext getChannelHandlerContext(int deviceCode) {
        return CONTEXT_MAP.get(deviceCode);
    }

    /**
     * 获取上下文
     *
     * @param ctx ctx
     */
    public static Integer getDeviceCode(ChannelHandlerContext ctx) {
        for (Map.Entry<Integer, ChannelHandlerContext> next : CONTEXT_MAP.entrySet()) {
            if (next.getValue() == ctx) {
                return next.getKey();
            }
        }
        return 0;
    }

}
